/*
 * mapa.h
 *
 *  Created on: 07/01/2011
 *      Author: julian
 */

#ifndef MAPA_H_
#define MAPA_H_

#include <list>
#include <vector>
#include "superficie.h"
#include "bscerrada.h"
#include "bezier.h"
#include "iobmp.h"
#include "textura.h"
#include "discretizador.h"
#include "texels.h"
#include "roca.h"
using namespace std;

class Mapa {
private:
	list<Superficie*>* almacenSuperficies;
	list<Roca*>* almacenRocas;
	list<BsplineCerrada*>* revoluciones;
	Bezier* perfil;
	Textura* texturaRoca;
	int w;
	int h;
public:
	Mapa(int w, int h){
		this->w = w;
		this->h = h;
		this->almacenSuperficies = new list<Superficie*>();
		this->almacenRocas = new list<Roca*>();
		this->revoluciones = new list<BsplineCerrada*>();
		this->perfil = NULL;
	}

	void setTexturaRoca(Textura* tex){
		this->texturaRoca = tex;
	}

	void establecerPerfil(Bezier* nuevoPerfil){
		//Bezier* aux = perfil;
		this->perfil = nuevoPerfil;
		//if (aux!=NULL) delete aux;
	}

	list<Superficie*>* getAlmacenSuperficies(){
		return this->almacenSuperficies;
	}

	list<Roca*>* getAlmacenRocas(){
		return this->almacenRocas;
	}

	void agregarRevolucion(BsplineCerrada* revolucion){
		Discretizador d;
		this->revoluciones->push_back(revolucion);
		Superficie* nuevaSup = new Superficie(*revolucion,*perfil);
		this->almacenSuperficies->push_back(nuevaSup);
		Roca* nuevaRoca = new Roca(*texturaRoca, *nuevaSup, d);
		this->almacenRocas->push_back(nuevaRoca);
	}

	int ancho(){
		return w;
	}

	int alto(){
		return h;
	}

	void dibujarSuelo(Textura* pasto){
		//TODO: Generar cuadraditos, como una superficie.
		//		Buscar tamaño adecuado para la aplicacion de la textura.
		glNormal3f(0, 0, 1);
		GLfloat mat_specular[] = { 1.0, 1.0, 1.0, 1.0 };
		GLfloat low_shininess[] = { 0.25 };
		glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
		glMaterialfv(GL_FRONT, GL_SHININESS, low_shininess);
		glPushMatrix();
		glTranslatef(-w/2,-h/2,0);
		pasto->enlazar();
		glBegin(GL_QUADS);
			glTexCoord2f(1.0,0.0);
			glVertex3f(w,0.0,0.0);
			glTexCoord2f(1.0,1.0);
			glVertex3f(w,h,0.0);
			glTexCoord2f(0.0,1.0);
			glVertex3f(0.0,h,0.0);
			glTexCoord2f(0.0,0.0);
			glVertex3f(0.0,0.0,0.0);
		glEnd();
		pasto->desenlazar();
		glDisable(GL_LIGHTING);
		glEnable(GL_BLEND);
		glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
		glBegin(GL_QUADS);
			glColor4f(0.173,0.231,0.188,1.0);
			glVertex3f(0.0,0.0,0.009);
			glColor4f(0.173,0.231,0.188,1.0);
			glVertex3f(w,0.0,0.009);
			glColor4f(0.173,0.231,0.188,0.0);
			glVertex3f(0.9*w,0.1*h,0.009);
			glColor4f(0.173,0.231,0.188,0.0);
			glVertex3f(0.1*w,0.1*h,0.009);
			///
			glColor4f(0.173,0.231,0.188,1.0);
			glVertex3f(w,0.0,0.009);
			glColor4f(0.173,0.231,0.188,1.0);
			glVertex3f(w,h,0.009);
			glColor4f(0.173,0.231,0.188,0.0);
			glVertex3f(0.9*w,0.9*h,0.009);
			glColor4f(0.173,0.231,0.188,0.0);
			glVertex3f(0.9*w,0.1*h,0.009);
			///
			glColor4f(0.173,0.231,0.188,1.0);
			glVertex3f(w,h,0.009);
			glColor4f(0.173,0.231,0.188,1.0);
			glVertex3f(0.0,h,0.009);
			glColor4f(0.173,0.231,0.188,0.0);
			glVertex3f(0.1*w,0.9*h,0.009);
			glColor4f(0.173,0.231,0.188,0.0);
			glVertex3f(0.9*w,0.9*h,0.009);
			///
			glColor4f(0.173,0.231,0.188,1.0);
			glVertex3f(0.0,h,0.009);
			glColor4f(0.173,0.231,0.188,1.0);
			glVertex3f(0.0,0.0,0.009);
			glColor4f(0.173,0.231,0.188,0.0);
			glVertex3f(0.1*w,0.1*h,0.009);
			glColor4f(0.173,0.231,0.188,0.0);
			glVertex3f(0.1*w,0.9*h,0.009);
		glEnd();
		glPopMatrix();
		glEnable(GL_LIGHTING);
		glDisable(GL_BLEND);
	}

	void dibujarMiniMapa(){
		list<BsplineCerrada*>::iterator itsup;
		float paso = 0.05;
		//Dibujado de las curvas
		for ( itsup=revoluciones->begin() ; itsup != revoluciones->end(); itsup++ ){
			glBegin(GL_LINE_STRIP);
				glColor3f(1.0,1.0,1.0);
				for(float i=0.0; i<=1; i+=paso){
					Coord v = (*itsup)->operator ()(i);
					float normX = v.x()/(this->w);
					float normY = v.y()/(this->h);
					glVertex2f(normX,normY);
				}
				Coord v = (*itsup)->operator ()(0);
				float normX = v.x()/(this->w);
				float normY = v.y()/(this->h);
				glVertex2f(normX,normY);
			glEnd();
		//Dibujado de los puntos de control
			glPointSize(5);
			glBegin(GL_POINTS);
				glColor3f(1.0,0.0,0.0);
				list<BsplineCerrada*>::iterator itsup2;
				for ( itsup2=revoluciones->begin() ; itsup2 != revoluciones->end(); itsup2++ ){
					vector<Coord> puntos = (*itsup2)->getPuntosControl();
					for(int i = 0; i<puntos.size(); i++){
						Coord coordenadas = puntos[i];
						float coordX = coordenadas.x()/this->w;
						float coordY = coordenadas.y()/this->h;
						glVertex2f(coordX,coordY);
					}
				}
			glEnd();/**/
		}
	}

	virtual ~Mapa(){
		list<BsplineCerrada*>::iterator it;
		list<Superficie*>::iterator it2;
		list<Roca*>::iterator it3;

		for ( it=revoluciones->begin() ; it != revoluciones->end(); it++ )
			delete *it;
		for ( it2=almacenSuperficies->begin() ; it2 != almacenSuperficies->end(); it2++ )
			delete *it2;
		for ( it3=almacenRocas->begin() ; it3 != almacenRocas->end(); it3++ )
			delete *it3;
		delete revoluciones;
		delete almacenSuperficies;
		delete almacenRocas;
		delete perfil;
		delete texturaRoca;
	}
};

#endif /* MAPA_H_ */
